package demo.gateway.filter;

import demo.gateway.metric.GatewayMetricsCollector;
import demo.gateway.metric.SSEResponseDecorator;
import demo.utils.JsonUtil;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * GlobalFilter是一个全局过滤器,用于处理所有路由的请求和响应。
 * <li>与GatewayFilter相比,GlobalFilter的作用范围更大,会应用到所有的路由上，不需要在路由配置中显式声明。
 * <li>常见使用场景:统一鉴权、访问日志记录、请求计时统计、限流、黑白名单控制。
 * <li>可以通过实现Ordered接口来控制过滤器的执行顺序，数字越小,优先级越高。
 * <p><br>
 * ServerWebExchange是Spring WebFlux中的一个核心接口，代表了HTTP请求-响应的完整交互过程。它包含了处理当前HTTP请求所需的所有信息。
 * <li>主要组成部分：请求相关、响应相关、会话信息、属性等。
 * <li>主要用途：请求参数解析和处理、请求头的读取和修改、响应内容的设置、会话管理、请求上下文数据传递、请求属性的存储
 * <p><br>
 * GatewayFilterChain是Spring Cloud Gateway中的过滤器链接口，用于管理和执行过滤器链中的下一个过滤器。它采用责任链模式实现过滤器的顺序执行。
 */
@Component
public class Filter1Logging implements GlobalFilter, Ordered {

    private static final Logger logger = LoggerFactory.getLogger(Filter1Logging.class);

    private MeterRegistry meterRegistry;

    private GatewayMetricsCollector metricsCollector;


    @Autowired
    public void setMeterRegistry(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
    }

    @Autowired
    public void setMetricsCollector(GatewayMetricsCollector metricsCollector) {
        this.metricsCollector = metricsCollector;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        long startTime = System.currentTimeMillis();

        metricsCollector.incrementRequests();
        ServerHttpRequest httpRequest = exchange.getRequest();
        // 记录请求大小
        String contentLength = httpRequest.getHeaders().getFirst(HttpHeaders.CONTENT_LENGTH);
        logger.info("请求大小：{} bytes", contentLength);
        if (contentLength != null) {
            metricsCollector.recordBytes(Long.parseLong(contentLength), 0);
        }
        print(httpRequest);

        // 添加自定义请求头
        ServerHttpRequest request = exchange.getRequest().mutate()
                .header("XXXX_header1", "value")
                .build();
        // 创建新的 exchange
        ServerWebExchange mutatedExchange = exchange.mutate()
                .request(request)
                .build();

        // 请求计数器
        Counter.builder("gateway.requests.total")
                .tag("path", exchange.getRequest().getPath().value())
                .register(meterRegistry)
                .increment();

        // 响应时间
        Timer.builder("gateway.request.duration")
                .tag("path", exchange.getRequest().getPath().value())
                .register(meterRegistry);
        // 存储属性
        exchange.getAttributes().put("startTime", System.currentTimeMillis());

        // 检查是否是SSE请求
        if (isSSERequest(request)) {
            String requestId = UUID.randomUUID().toString();

            // 包装响应，以便监控
            ServerHttpResponse response = exchange.getResponse();
            SSEResponseDecorator decorator = new SSEResponseDecorator(response);

            return chain.filter(exchange.mutate().response(decorator).build());
        }

        return chain.filter(exchange)
                .doFinally(signalType -> {
                    // 记录响应时间
                    long duration = System.currentTimeMillis() - startTime;
                    meterRegistry.timer("gateway.request.duration")
                            .record(duration, TimeUnit.MILLISECONDS);

                    metricsCollector.recordResponseTime(duration);
                    logger.info("请求耗时：{} ms", duration);

                    // 记录响应大小
                    ServerHttpResponse response = exchange.getResponse();
                    String responseLength = response.getHeaders().getFirst(HttpHeaders.CONTENT_LENGTH);
                    if (responseLength != null) {
                        logger.info("响应大小：{} bytes", responseLength);
                        metricsCollector.recordBytes(0, Long.parseLong(responseLength));
                    }


                    // 记录错误
                    HttpStatusCode statusCode = response.getStatusCode();
                    logger.error("服务器响应码: {}", statusCode);

                    metricsCollector.decrementConcurrentRequests();

                });
    }


    private static void print(ServerHttpRequest httpRequest) {
        MultiValueMap<String, String> queryParams = httpRequest.getQueryParams();
        HttpMethod httpMethod = httpRequest.getMethod();
        System.err.printf("%s: %s, queryParam: %s %n", httpMethod.name(), httpRequest.getPath(), queryParams);

        HttpHeaders headers = httpRequest.getHeaders();
        System.err.println("Headers: " + JsonUtil.toJSONString(headers));

        Map<String, Object> attributes = httpRequest.getAttributes();


    }


    private boolean isSSERequest(ServerHttpRequest request) {
        // 检查Accept头是否为text/event-stream
        List<String> acceptHeaders = request.getHeaders().get(HttpHeaders.ACCEPT);
        return acceptHeaders != null &&
                acceptHeaders.stream()
                        .anyMatch(header -> header.contains("text/event-stream"));
    }

    @Override
    public int getOrder() {
        return 10; // 过滤器执行顺序
    }
}
